package com.ideaaedi.zoo.diy.feature.msg.sms.impl.sms4j.core;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.aliyun.config.AlibabaFactory;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.api.verify.PhoneVerify;
import org.dromara.sms4j.baidu.config.BaiduFactory;
import org.dromara.sms4j.budingyun.config.BudingV2Factory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enums.ConfigType;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.dromara.sms4j.core.proxy.processor.BlackListProcessor;
import org.dromara.sms4j.core.proxy.processor.BlackListRecordingProcessor;
import org.dromara.sms4j.core.proxy.processor.CoreMethodParamValidateProcessor;
import org.dromara.sms4j.core.proxy.processor.RestrictedProcessor;
import org.dromara.sms4j.core.proxy.processor.SingleBlendRestrictedProcessor;
import org.dromara.sms4j.ctyun.config.CtyunFactory;
import org.dromara.sms4j.danmi.config.DanMiFactory;
import org.dromara.sms4j.dingzhong.config.DingZhongFactory;
import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
import org.dromara.sms4j.jdcloud.config.JdCloudFactory;
import org.dromara.sms4j.jg.config.JgFactory;
import org.dromara.sms4j.lianlu.config.LianLuFactory;
import org.dromara.sms4j.luosimao.config.LuoSiMaoFactory;
import org.dromara.sms4j.mas.config.MasFactory;
import org.dromara.sms4j.netease.config.NeteaseFactory;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
import org.dromara.sms4j.qiniu.config.QiNiuFactory;
import org.dromara.sms4j.starter.adepter.ConfigCombineMapAdaptor;
import org.dromara.sms4j.starter.configration.SmsBlendsInitializer;
import org.dromara.sms4j.submail.config.SubMailFactory;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
import org.dromara.sms4j.zhutong.config.ZhutongFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;


/**
 * <pre>
 * 增强{@link SmsBlendsInitializer}，增强点：
 * 1.使用{@link BaseProviderFactoryWrapper#wrap(BaseProviderFactory)}包装{@link BaseProviderFactory}
 * </pre>
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 1.0.0
 */

@Slf4j
public class SmsBlendsInitializerExt {
    private final List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList;
    
    private final SmsConfig smsConfig;
    private final Map<String, Map<String, Object>> blends;
    private final ObjectProvider<SmsReadConfig> extendsSmsConfigs;
    
    public SmsBlendsInitializerExt(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList,
                                SmsConfig smsConfig,
                                Map<String, Map<String, Object>> blends,
                                ObjectProvider<SmsReadConfig> extendsSmsConfigs) {
        this.factoryList = factoryList;
        this.smsConfig = smsConfig;
        this.blends = blends;
        this.extendsSmsConfigs = extendsSmsConfigs;
        onApplicationEvent();
    }
    
    public void onApplicationEvent() {
        this.registerDefaultFactory();
        // 注册短信对象工厂
        if (!CollectionUtils.isEmpty(factoryList)) {
            for (BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig> baseProviderFactory : factoryList) {
                ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(baseProviderFactory));
            }
        }
        //如果手机号校验器存在实现，则注册手机号校验器（暂不可用）
        ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
        if (loader.iterator().hasNext()) {
            loader.forEach(f -> {
                SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f));
            });
        } else {
            SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
        }
        //注册执行器实现
        if(this.smsConfig.getRestricted()){
            SmsProxyFactory.addPreProcessor(new RestrictedProcessor());
            SmsProxyFactory.addPreProcessor(new BlackListProcessor());
            SmsProxyFactory.addPreProcessor(new BlackListRecordingProcessor());
            SmsProxyFactory.addPreProcessor(new SingleBlendRestrictedProcessor());
        }
        if (ConfigType.YAML.equals(this.smsConfig.getConfigType())) {
            //持有初始化配置信息
            Map<String, Map<String, Object>> blendsInclude = new ConfigCombineMapAdaptor<String, Map<String, Object>>();
            blendsInclude.putAll(this.blends);
            int num = 0;
            for (SmsReadConfig smsReadConfig : extendsSmsConfigs) {
                String key = SmsReadConfig.class.getSimpleName() + num;
                Map<String, Object> insideMap = new HashMap<>();
                insideMap.put(key, smsReadConfig);
                blendsInclude.put(key, insideMap);
                num++;
            }
            EnvirmentHolder.frozenEnvirmet(smsConfig, blendsInclude);
            // 解析供应商配置
            for (String configId : blends.keySet()) {
                Map<String, Object> configMap = blends.get(configId);
                Object supplierObj = configMap.get(Constant.SUPPLIER_KEY);
                String supplier = supplierObj == null ? "" : String.valueOf(supplierObj);
                supplier = StrUtil.isEmpty(supplier) ? configId : supplier;
                BaseProviderFactory<SmsBlend, SupplierConfig> providerFactory = (BaseProviderFactory<SmsBlend, org.dromara.sms4j.api.universal.SupplierConfig>) ProviderFactoryHolder.requireForSupplier(supplier);
                if (providerFactory == null) {
                    log.warn("创建\"{}\"的短信服务失败，未找到供应商为\"{}\"的服务", configId, supplier);
                    continue;
                }
                configMap.put("config-id", configId);
                SmsUtils.replaceKeysSeparator(configMap, "-", "_");
                JSONObject configJson = new JSONObject(configMap);
                org.dromara.sms4j.api.universal.SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
                SmsFactory.createSmsBlend(supplierConfig);
            }
        }
        
        
    }
    
    /**
     * 注册默认工厂实例
     */
    private void registerDefaultFactory() {
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(AlibabaFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(CloopenFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(CtyunFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(EmayFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(HuaweiFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(NeteaseFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(TencentFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(UniFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(YunPianFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(ZhutongFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(LianLuFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(DingZhongFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(QiNiuFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(ChuangLanFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(JgFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(BudingV2Factory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(MasFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(BaiduFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(LuoSiMaoFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(SubMailFactory.instance()));
        ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(DanMiFactory.instance()));
        if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
            if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
                ProviderFactoryHolder.registerFactory(BaseProviderFactoryWrapper.wrap(JdCloudFactory.instance()));
            }
            log.debug("加载内置运营商完成！");
        }
        
    }
}
